<?php


namespace app\common\middleware;


use ReflectionClass;
use support\exception\BadException;
use Webman\Http\Request;
use Webman\Http\Response;
use Webman\MiddlewareInterface;

abstract class BaseAuthMiddleware implements MiddlewareInterface
{
    protected static string $allAuthStr = "*";
    protected static string $authorizationKey = "Authorization";


    /**
     * @var array|mixed
     */
    protected $noNeedLogin = [];
    /**
     * @var array|mixed
     */
    protected $noNeedRight = [];
    protected \ReflectionMethod $method;
    protected string $token;

    public function process(Request $request, callable $handler): Response
    {
        // 通过反射获取控制器哪些方法不需要登录
        $controller = new ReflectionClass($request->controller);
        $properties = $controller->getDefaultProperties();
        $this->noNeedLogin = $properties['noNeedLogin'] ?? [];
        $this->noNeedRight = $properties['noNeedRight'] ?? [];
        $this->method = $controller->getMethod($request->action);
        $request->os = $request->header("os");

        // 访问的方法需要登录
        if (in_array(self::$allAuthStr, $this->noNeedLogin)
            || in_array($request->action, $this->noNeedLogin)) {
            return $handler($request);
        }

        $token = $request->header(self::$authorizationKey);
        if (!$token) {
            throw new BadException("登录异常", 401);
        }
        $this->token = trim(str_replace("Bearer ", "", $token));
        $this->checkAndSetRequest($request);

        if (in_array(self::$allAuthStr, $this->noNeedRight)
            || in_array($request->action, $this->noNeedRight)) {
            return $handler($request);
        }
        return $this->checkAuthRight($request, $handler);
    }

    /**
     * 验证登录信息以及设置request的登录信息
     * @param Request $request
     * @return mixed
     */
    protected abstract function checkAndSetRequest(Request $request);

    /**
     * 根据系统验证权限
     * @param Request $request
     * @param callable $handler
     * @return mixed
     */
    protected abstract function checkAuthRight(Request $request, callable $handler);
}